from typing import Dict, Union

from stethistics.checks.backend import _ip_aliases_check, _concentration_check, _subnet_check, _roommates_check, \
    _identical_check


def raw_aliases_check(crawl_data: dict, threshold: int) -> Dict[str, Union[int, list]]:
    """checks for nodes with too much different addresses"""
    return {"threshold": threshold,
            "results":
                [{"count": len(node['Seen node IDs']),
                  "ip": node["IP address"], "udp": node["UDP port"],
                  "addresses": sorted(node['Seen node IDs'])}
                 for node in
                 sorted(crawl_data["up"],
                        key=lambda x: (len(x['Seen node IDs']),
                                       tuple(map(lambda y: int(y), x["IP address"].split('.')))), reverse=True)
                 if len(node['Seen node IDs']) >= threshold]}


def raw_roommates_check(crawl_data: dict, threshold: int) -> Dict[str, Union[int, dict]]:
    """checks for IP addresses with too much different nodes"""
    return {"threshold": threshold,
            "results":
                {key: {"count": len(value), "udp": sorted(value)}
                 for key, value in
                 sorted(_roommates_check(crawl_data).items(),
                        key=lambda x: (len(x[1]), tuple(map(lambda y: int(y), x[0].split('.')))),
                        reverse=True)
                 if len(value) >= threshold}}


def raw_ip_aliases_check(crawl_data: dict, threshold: int) -> Dict[str, Union[int, dict]]:
    """checks for IP addresses with too much different nodes"""
    return {"threshold": threshold,
            "results":
                {ip:
                     {k: {"count": len(v), "values": sorted(v)}
                      for k, v
                      in res.items()}
                 for ip, res in
                 sorted(list(_ip_aliases_check(crawl_data).items()),
                        key=lambda x: len((list(x))[1]["addresses"]), reverse=True)
                 if len(res["addresses"]) >= threshold}}


def raw_subnet_check(crawl_data: dict, threshold: int) -> Dict[str, Union[int, list]]:
    """checks for IP addresses on the same /24 subnet"""
    return {"threshold": threshold,
            "results": [
                {"count": len(value),
                 "network": key,
                 "addresses": sorted(tuple(value), key=lambda x: int(x[0].split('.')[-1]))}
                for key, value in
                sorted(_subnet_check(crawl_data).items(), key=lambda x: len(x[1]), reverse=True)
                if len(value) >= threshold]}


def raw_concentration_check(crawl_data: dict, threshold: int) -> Dict[str, Union[int, list]]:
    """checks for grouped node addresses"""
    return {"threshold": threshold,
            "results": sorted(_concentration_check(crawl_data, threshold), key=lambda x: x["count"],
                              reverse=True)}


def raw_identical_check(crawl_data: dict, threshold: int) -> Dict[str, Union[int, dict]]:
    """checks for nodes sharing the same id"""
    return {"threshold": threshold, "results": {k: {"count": len(v), "nodes": v} for k, v in
                                                sorted(_identical_check(crawl_data).items(),
                                                       key=lambda x: (len(x[1]), x[0]), reverse=True) if
                                                len(v) >= threshold}}
